{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Multi-Link usage: CHP with fixed heat-power ratio\n",
    "\n",
    "This notebook if a demonstration of Link with multiple outputs: Combined-Heat-and-Power (CHP) with fixed heat-power ratio\n",
    "\n",
    "For a CHP with a more complicated heat-power feasible operational area, see the [power-to-gas example](https://github.com/PyPSA/PyPSA/blob/master/examples/notebooks/power-to-gas-boiler-chp.ipynb)\n",
    "\n",
    "This example demonstrates a Link component with more than one bus output (\"bus2\" in this case). In general links can have many output buses.\n",
    "\n",
    "In this example a CHP must be heat-following because there is no other supply of heat to the bus \"Frankfurt heat\"."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pypsa, numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First tell PyPSA that links will have a 2nd bus by overriding the component_attrs. This can be done for as many buses as you need with format busi for i = 2,3,4,5,...."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "override_component_attrs = pypsa.descriptors.Dict({k : v.copy() for k,v in pypsa.components.component_attrs.items()})\n",
    "override_component_attrs[\"Link\"].loc[\"bus2\"] = [\"string\",np.nan,np.nan,\"2nd bus\",\"Input (optional)\"]\n",
    "override_component_attrs[\"Link\"].loc[\"efficiency2\"] = [\"static or series\",\"per unit\",1.,\"2nd bus efficiency\",\"Input (optional)\"]\n",
    "override_component_attrs[\"Link\"].loc[\"p2\"] = [\"series\",\"MW\",0.,\"2nd bus output\",\"Output\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "network = pypsa.Network(override_component_attrs=override_component_attrs)\n",
    "\n",
    "network.add(\"Bus\", \"Frankfurt\", carrier=\"AC\")\n",
    "network.add(\"Load\", \"Frankfurt\", bus=\"Frankfurt\", p_set=5)\n",
    "\n",
    "\n",
    "network.add(\"Bus\", \"Frankfurt heat\", carrier=\"heat\")\n",
    "network.add(\"Load\", \"Frankfurt heat\", bus=\"Frankfurt heat\", p_set=3)\n",
    "\n",
    "\n",
    "network.add(\"Bus\", \"Frankfurt gas\", carrier=\"gas\")\n",
    "network.add(\"Store\",\n",
    "            \"Frankfurt gas\",\n",
    "            e_initial=1e6,\n",
    "            e_nom=1e6,\n",
    "            bus=\"Frankfurt gas\")\n",
    "\n",
    "network.add(\"Link\",\n",
    "            \"OCGT\",\n",
    "            bus0=\"Frankfurt gas\",\n",
    "            bus1=\"Frankfurt\",\n",
    "            p_nom_extendable=True,\n",
    "            capital_cost=600,\n",
    "            efficiency=0.4)\n",
    "\n",
    "\n",
    "network.add(\"Link\",\n",
    "            \"CHP\",\n",
    "            bus0=\"Frankfurt gas\",\n",
    "            bus1=\"Frankfurt\",\n",
    "            bus2=\"Frankfurt heat\",\n",
    "            p_nom_extendable=True,\n",
    "            capital_cost=1400,\n",
    "            efficiency=0.3,\n",
    "            efficiency2=0.3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "network.lopf();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "network.loads_t.p"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "network.links_t.p0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "network.links_t.p1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "network.links_t.p2"
   ]
  }
 ],
 "metadata": {
  "@webio": {
   "lastCommId": null,
   "lastKernelId": null
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
